package com.yejiali.backend.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yejiali.backend.common.apicode.ResponseCodeEnum;
import com.yejiali.backend.common.constant.SystemConstant;
import com.yejiali.backend.entity.Comments;
import com.yejiali.backend.entity.Users;
import com.yejiali.backend.entity.VideoLikes;
import com.yejiali.backend.entity.Videos;
import com.yejiali.backend.entity.dto.*;
import com.yejiali.backend.entity.vo.VideosVO;
import com.yejiali.backend.mapper.CommentsMapper;
import com.yejiali.backend.mapper.UsersMapper;
import com.yejiali.backend.mapper.VideoLikesMapper;
import com.yejiali.backend.mapper.VideosMapper;
import com.yejiali.backend.response.Response;
import com.yejiali.backend.service.VideosService;
import com.yejiali.backend.util.RedisUtil;
import com.yejiali.backend.util.UrlUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 视频作品表(Videos)表服务实现类
 *
 * @author yejiali
 * @since 2025-07-21 15:20:42
 */
@Service
public class VideosServiceImpl extends ServiceImpl<VideosMapper, Videos> implements VideosService {


    @Autowired
    private UsersMapper usersMapper;

    @Autowired
    private CommentsMapper commentsMapper;

    @Autowired
    private VideoLikesMapper videoLikesMapper;

    @Autowired
    private RedisUtil redisUtil;

    /**
     * 获取视频列表
     * @param pageNum
     * @param pageSize
     * @return
     */
    @Override
    public Response<VideoListDTO> getVideos(int pageNum, int pageSize) {
        //查询视频列表
        QueryWrapper<Videos> queryWrapper = new QueryWrapper<>();
        //按时间降序排序
        queryWrapper.orderByDesc("publish_time");
        //分页查询
        Page<Videos> page = new Page<>(pageNum, pageSize);
        page = this.page(page, queryWrapper);
        List<Videos> records = page.getRecords();
        //没有记录了
        if(records.isEmpty()){
            return Response.success(new VideoListDTO(new ArrayList<>(), false));
        }
        List<VideosVO> videosVOs = setNicknameAndCommentCount(records);
        //封装响应对象
        VideoListDTO videoListDTO = new VideoListDTO(videosVOs, !records.isEmpty());
        //返回响应对象
        return Response.success(videoListDTO);
    }


    /**
     * 根据目前观看推荐视频
     *
     * @param videoId
     * @return
     */
    @Override
    public Response<List<VideosVO>> recommendVideos(Long videoId) {
        //查找当前观看视频所在的分区
        Videos video = getById(videoId);
        if (video == null || video.getIsDeleted() == 1) {
            return Response.error(ResponseCodeEnum.NOT_FOUND.getCode(), "视频不存在");
        }
        //根据分区查看推荐视频
        LambdaQueryWrapper<Videos> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Videos::getTags, video.getTags());
        lambdaQueryWrapper.eq(Videos::getStatus, SystemConstant.PUBLISHED_VIDEO);
        //这里我直接给了一个固定值
        Page<Videos> page = new Page<>(1, 15);
        page(page, lambdaQueryWrapper);
        List<Videos> videosList = page.getRecords();
        if(videosList.isEmpty()){
            return Response.success(new ArrayList<>());
        }
        List<VideosVO> videosVOList = setNicknameAndCommentCount(videosList);
        return Response.success(videosVOList);
    }

    /**
     * 设置昵称和评论数
     * @param videos
     */
    private List<VideosVO> setNicknameAndCommentCount(List<Videos> videos){
        List<VideosVO> videosVOs = BeanUtil.copyToList(videos, VideosVO.class);
        //提取用户id，和视频id
        Set<Long> uploaderIds = new HashSet<>();
        List<Long> videoIds = new ArrayList<>();
        for(VideosVO video : videosVOs){
            uploaderIds.add(video.getUploaderId());
            videoIds.add(video.getVideoId());
        }
        //批量查询用户信息和评论数
        Map<Long, String> uploaderMap = new HashMap<>();
        Map<Long, Long> commentCountMap = new HashMap<>();
        if(!uploaderIds.isEmpty()){
            List<Users> uploaders = usersMapper.selectBatchIds(uploaderIds);
            //key：用户id，value：用户昵称
            uploaderMap = uploaders.stream()
                    .collect(Collectors.toMap(Users::getUserId, Users::getNickname));
        }
        if(!videoIds.isEmpty()){
            QueryWrapper<Comments> queryCount = new QueryWrapper<>();
            queryCount.select("video_id", "count(*) as comment_count")
                    .in("video_id", videoIds)
                    .groupBy("video_id");
            List<Map<String, Object>> maps = commentsMapper.selectMaps(queryCount);
            //转储到commentCountMap
            for(Map<String, Object> map : maps){
                Long videoId = Long.valueOf(map.get("video_id").toString());
                Long commentCount = Long.valueOf(map.get("comment_count").toString());
                commentCountMap.put(videoId, commentCount);
            }
        }
        for (VideosVO video : videosVOs) {
            //设置博主昵称
            String uploaderName = uploaderMap.get(video.getUploaderId());
            video.setUploaderName(uploaderName);
            //设置视频评论数
            Long commentCount = commentCountMap.get(video.getVideoId());
            video.setCommentCount(commentCount);
        }
        return videosVOs;
    }

    /**
     * 上传视频
     *
     * @param uploadVideoDTO
     * @return
     */
    @Override
    public Response<String> uploadVideo(UploadVideoDTO uploadVideoDTO) {
        //获取上传者id
        Long uploaderId = uploadVideoDTO.getUploaderId();
        //判断上传者是否存在
        Users user = usersMapper.selectById(uploaderId);
        if (user == null) {
            return Response.error(ResponseCodeEnum.NOT_FOUND.getCode(), "该用户不存在");
        }
        //验证url地址格式及有效性
        String videoUrl = uploadVideoDTO.getPlayUrl();
        if (!(UrlUtil.isValidUrl(videoUrl) && UrlUtil.isUrlReachable(videoUrl))) {
            return Response.error(ResponseCodeEnum.PARAM_ERROR.getCode(), "视频url地址格式错误");
        }
        Videos insertVideo = BeanUtil.copyProperties(uploadVideoDTO, Videos.class);
        //插入数据
        save(insertVideo);
        return Response.success("上传成功");
    }


    /**
     * 获取视频详情
     *
     * @param videoId
     * @return
     */
    @Override
    public Response<VideoDetailDTO> getVideoDetail(Long videoId, Long userId) {
        //判断视频是否存在
        Videos video = getById(videoId);
        if (video == null || video.getIsDeleted() == 1) {
            return Response.error(ResponseCodeEnum.NOT_FOUND.getCode(), "视频不存在");
        }
        //返回视频详情
        VideoDetailDTO videoDetailDTO = BeanUtil.copyProperties(video, VideoDetailDTO.class);
        //获取视频点赞数
        String key = "video:likeCount:" + videoId.toString();
        Object countObj = redisUtil.get(key);
        Long likeCount = 0L;
        //命中
        if (countObj != null) {
            // 无论Redis返回Integer还是Long，通过toString转为Long
            likeCount = Long.valueOf(countObj.toString());
        } else {
            // 未命中缓存，查询数据库
            LambdaQueryWrapper<VideoLikes> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(VideoLikes::getVideoId, videoId);
            likeCount = videoLikesMapper.selectCount(lambdaQueryWrapper);
            redisUtil.set(key, likeCount);
        }
        videoDetailDTO.setLikeCount(likeCount);
        //根据登录状态查询我是否点赞
        if(userId==null){
            videoDetailDTO.setIsLike(false);
            return Response.success(videoDetailDTO);
        }
        //先在redis中查，未命中再去查数据库
        String likeUserKey = "video:likeUser:" + videoId;
        boolean isLiked = redisUtil.sHasKey(likeUserKey, userId);
        if(!isLiked){
            LambdaQueryWrapper<VideoLikes> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(VideoLikes::getVideoId, videoId)
                    .eq(VideoLikes::getUserId, userId);
            isLiked=videoLikesMapper.selectOne(lambdaQueryWrapper)!=null;
            if(isLiked){
                //缓存到redis中
                redisUtil.sSet(likeUserKey, userId);
            }
        }
        videoDetailDTO.setIsLike(isLiked);
        return Response.success(videoDetailDTO);
    }
}




